package com.iwhale.zcm.utils;

import com.jcraft.jsch.*;
import com.ztesoft.zsmart.core.log.ZSmartLogger;
import org.apache.commons.io.IOUtils;

import java.io.*;
import java.util.Properties;

/**
 * Description: <br>
 * xxx
 *
 * @author lu.shuan
 * @date 2019/8/13 $<br>
 * @since V1.0 <br>
 */
public final class SSHUtils {

    public static final ZSmartLogger LOGGER = ZSmartLogger.getLogger(SSHUtils.class);

    private static final String ENCODING = "UTF-8";

    private SSHUtils() {

    }

    public static Session getJSchSession(String userName, String password, String host, Integer port, Integer timeOut) {
        JSch jsch = new JSch();
        Session session = null;
        try {
            session = jsch.getSession(userName, host, port);
            session.setPassword(password);
            // 只使用密码认证，关闭gssapi认证 提升session.connect 连接效率
            // session.setConfig("PreferredAuthentications", "password");
            // 第一次访问服务器不用输入yes
            Properties config = new Properties();
            config.put("StrictHostKeyChecking", "no");
            session.setConfig(config);
            session.setTimeout(timeOut);
            session.connect();
        } catch (JSchException e) {
            LOGGER.error(e.getMessage());
        }
        return session;
    }

    public static String shellCommandByJSch(Session session, String command) {
        StringBuilder result = new StringBuilder();
        Channel channel = null;
        OutputStream outputstream_for_the_channel = null;
        InputStream inputstream_from_the_channel = null;
        PrintStream commander = null;
        BufferedReader br = null;
        try {
            channel = session.openChannel("shell");
            outputstream_for_the_channel = channel.getOutputStream();
            commander = new PrintStream(outputstream_for_the_channel, true, ENCODING);
            channel.connect();
            commander.println(command);
            commander.println("exit");
            commander.close();
            inputstream_from_the_channel = channel.getInputStream();
            br = new BufferedReader(new InputStreamReader(inputstream_from_the_channel, ENCODING));
            String line;
            while ((line = br.readLine()) != null) {
                result.append(line);
                LOGGER.info(line);
            }
        } catch (JSchException e) {
            LOGGER.error(e.getMessage());
        } catch (IOException e) {
            LOGGER.error(e.getMessage());
        } finally {
            channelDisconnect(channel);
            opsClose(outputstream_for_the_channel);
            ipsClose(inputstream_from_the_channel);
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    LOGGER.error(e);
                }
            }
        }

        // session.disconnect();
        return result.toString();
    }


    public static String execCommandByJSch(Session session, String command) {
        String result = null;
        ChannelExec channelExec = null;
        InputStream in = null;
        try {
            channelExec = (ChannelExec) session.openChannel("exec");
            in = channelExec.getInputStream();
            channelExec.setCommand(command);
            channelExec.setErrStream(System.err);
            channelExec.connect();
            result = IOUtils.toString(in, ENCODING);
        } catch (JSchException e) {
            LOGGER.error(e.getMessage());
        } catch (IOException e) {
            LOGGER.error(e.getMessage());
        } finally {
            channelDisconnect(channelExec);
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    LOGGER.error(e.getMessage());
                }
            }
        }
        return result;
    }

    private static void ipsClose(InputStream inputstream_from_the_channel) {
        if (inputstream_from_the_channel != null) {
            try {
                inputstream_from_the_channel.close();
            } catch (IOException e) {
                LOGGER.error(e);
            }
        }
    }

    private static void opsClose(OutputStream outputstream_for_the_channel) {
        if (outputstream_for_the_channel != null) {
            try {
                outputstream_for_the_channel.close();
            } catch (IOException e) {
                LOGGER.error(e);
            }
        }
    }

    private static void channelDisconnect(Channel channel) {
        if (channel != null) {
            channel.disconnect();
        }
    }

}
